#ifndef XGE_XATEXIT_MANAGER_H_
#define XGE_XATEXIT_MANAGER_H_
#include "xge_common_config.h"
#include "xallstatic.h"
#include "xdata_structure.h"
#include "xstring.h"


namespace xge{
namespace xge_internal{

  // An at exit manager is a class to manage the priority of the destruction of
  // certain stuff
  // Like:
  // we want all the resource exit before the SYS_LOG (maybe) ,
  // so we may destroy the SYS_LOG at last
  // the same goes to the thread exit stuff 
  // This class MUST initialize before everything
  // so the best way to deal with it is not do any
  // global static object which have dependence of this class
  // This class do not need destroy 

  class AtExitManager: public AllStatic{
  private:
    typedef void (*SystemLogCallback)(void);
    typedef struct AtExitProxy {
      typedef bool (*AtExitProxyRoutine)( void* arugment );    
      // this is the argument which will pass into the
      // AtExitProxyRoutine function
      // therefore , should make it available until the
      // call the AtExitProxyRoutine
      AtExitProxyRoutine routine;
      void* argument;
      size_t priority; 
      String error_msg;
      bool operator < ( const AtExitProxy& proxy ) const {
        //reverse the operator
        //since the lower the more latter to be executed
        return priority < proxy.priority ;
      }

      AtExitProxy(
        AtExitProxyRoutine r,
        void* a,
        size_t p,
        const String& msg
        ) : routine(r),argument(a),priority(p),error_msg(msg){}
        
    };
  public:
    // Initialize the XAtExitManager
    // You should call this function before any thing using this manager
    static bool Initialize();
    // Register the at exit proxy
    // before this time , I always use a virtual class for proxy
    // now I use function pointer , since it will leave out us for
    // managing the memory
    // This function is not thread safe 
    static bool RegisterProxy (
      AtExitProxy::AtExitProxyRoutine routine, // routine pointer
      void* argument ,
      size_t priority,
      const String& msg
      );
    // Get the until now the most biggest priority
    static size_t GetUntilNowMaxPriority() {
      return kUntilNowMaxPriority;
    }
    // Register the system log call back
    static void RegisterSystemLogCallback( SystemLogCallback callback ){
      if( kSystemLogCallback == NULL ) {
        kSystemLogCallback = callback;
      }
    }

#ifdef _DEBUG
  private:
    static bool CheckInitializeOrNot();
#endif

  private:
    // Using the priority queue as our default data structure
    typedef xge::priority_queue< AtExitProxy >::PriorityQueue ProxyQueue;
    static size_t kUntilNowMaxPriority;
    static ProxyQueue* kProxyQueuePtr ;
    static SystemLogCallback kSystemLogCallback;
    // Internal register at exit main function
    static void __cdecl AtExitMain(void);
  };

}// namespace xge_internal
}//namespace xge


#endif // XGE_XATEXIT_MANAGER_H_